/**
 *日期类格式转换
 */
(function () {
    var MONTH_NAMES = ['January', 'February', 'March', 'April', 'May', 'June', 'July', 'August', 'September', 'October', 'November', 'December',
            'Jan', 'Feb', 'Mar', 'Apr', 'May', 'Jun', 'Jul', 'Aug', 'Sep', 'Oct', 'Nov', 'Dec'],
        DAY_NAMES = ['Sunday', 'Monday', 'Tuesday', 'Wednesday', 'Thursday', 'Friday', 'Saturday',
            'Sun', 'Mon', 'Tue', 'Wed', 'Thu', 'Fri', 'Sat'],
        CHI = {'0':'零', '1':'一', '2':'二', '3':'三', '4':'四', '5':'五', '6':'六', '7':'七', '8':'八', '9':'九'};
    //阿拉伯数字转换中文，不进位 toChi
    var N2C = function (year) {
        Object.each(CHI, function (v, k) {
            year = year.replace(/k/g, v);
        }, this);
        return year;
    };
    //中文转换阿拉伯数字，纯替换 toNum
    var C2N = function (year) {
        Object.each(CHI, function (v, k) {
            year = year.replace(/v/g, k);
        }, this);
        return year;
    };
    //阿拉伯数字转换中文,进位,只支持到十位数  toChiNum
    var _N2C = function (n) {
        var num = Number.from(n);
        var s = String.from(n);
        if (num > 9 && num < 20) {
            s = '十' + s.charAt(1);
        } else if (num > 19) {
            s = s.charAt(0) + '十' + s.charAt(1);
        }
        s = N2C(s);
        if (num != 0)s = s.replace(/零/g, '');
        return s;
    };
    //中文转换阿拉伯数字，带进位，支持2位数 toNum2
    var _C2N = function (year) {
        var l = year.length;
        if (year == '十')return 10;
        if (l == 1 && '十' != year)return C2N(year);
        //十一 到 十九
        if (l == 2 && '十' != year.charAt(l - 1))return C2N(year.replace(/十/g, '一'));
        //二十 到 九十 的整数
        if (l == 2 && '十' == year.charAt(l - 1)) return C2N(year.replace(/十/g, '零'));
        //二十一 到 九十九 的三位中文数字
        if (l == 3)return C2N(year.replace(/十/g, ''));

    };
    //自动补零
    var addzero = function (x) {
        return(x < 0 || x > 9 ? '' : '0') + x;
    };
    var compare = function (d1, f1, d2, f2) {
        d1 = str2date(d1, f1);
        d2 = str2date(d2, f2);
        if (d1 == 0 || d2 == 0) {
            alert("format格式转换有问题");
            return;
        } else if (d1 > d2) {
            return true;
        }
        return false;
    };
    //将date对象转为fmt格式的字符串
    var date2str = function (date, fmt) {
        fmt = String.from(fmt);
        var result = '', i_format = 0, c, token,
            y = String.from(date.getFullYear()),
            M = date.getMonth() + 1,
            d = date.getDate(),
            E = date.getDay(),
            H = date.getHours(),
            m = date.getMinutes(),
            s = date.getSeconds(),
            h = (H == 0) ? 12 : ((H > 12) ? H - 12 : H),
            K = (H > 11) ? H - 12 : H,
            k = H + 1,
            v = {
                'y':String.from(y),
                'yy':y.substring(2, 4),
                'yyyy':y,
                'M':M,
                'MM':addzero(M),
                'MMM':MONTH_NAMES[M - 1],
                'NNN':MONTH_NAMES[M + 11],
                'd':d,
                'dd':addzero(d),
                'E':DAY_NAMES[E + 7],
                'EE':DAY_NAMES[E],
                'H':H,
                'HH':addzero(H),
                'h':h,
                'hh':addzero(h),
                'k':k,
                'kk':addzero(k),
                'K':K,
                'KK':addzero(K),
                'a':(H > 11) ? 'PM' : 'AM',
                'm':m,
                'mm':addzero(m),
                's':s,
                'ss':addzero(s)
            };
        v['NNNN'] = N2C(y);
        v['NN'] = N2C(v['yy']);
        v['N'] = N2C(v['y']);
        v['Y'] = _N2C(M);
        v['R'] = _N2C(d);
        v['S'] = _N2C(h);
        v['T'] = _N2C(v['H']);
        v['U'] = _N2C(K);
        v['V'] = _N2C(k);
        v['F'] = _N2C(m);
        v['W'] = _N2C(s);
        while (i_format < fmt.length) {
            c = fmt.charAt(i_format);
            token = '';
            while ((fmt.charAt(i_format) == c) && (i_format < fmt.length)) {
                token += fmt.charAt(i_format++);
            }
            if (v[token] != null) {
                result = result + v[token];
            } else {
                result = result + token;
            }
        }
        return result;
    };
    var _isInteger = function (v) {
        var d = "1234567890", i;
        for (i = 0; i < v.length; i++) {
            if (d.indexOf(v.charAt(i)) == -1)return false;
        }
        return true;
    };
    var _isInteger_chi = function (v) {
        var d = "零一二三四五六七八九十", i;
        for (i = 0; i < v.length; i++) {
            if (d.indexOf(v.charAt(i)) == -1)
                return false;
        }
        return true;
    };
    var _getInt = function (str, i, ml, mal) {
        for (var x = mal; x >= ml; x--) {
            var token = str.substring(i, i + x);
            if (token.length < ml) {
                return null;
            }
            if (_isInteger(token)) {
                return token;
            }
        }
        return null;
    };
    var _getInt2 = function (str, i, ml, mal) {
        for (var x = mal; x >= ml; x--) {
            var token = str.substring(i, i + x);
            if (token.length < ml) {
                return null;
            }
            if (token) {
                return token;
            }
        }
        return null;
    };
    var _getInt_month = function (str, i) {
        for (var x = 2; x >= 1; x--) {
            var token = str.substring(i, i + x);
            if (token.length < 1) {
                return null;
            }
            if (token.length == 1) {
                return token;
            }
            if (['十一', '十二'].contains(token)) {
                return token;
            }
        }
        return null;
    };
    var _getInt_date = function (str, i) {
        for (var x = 3; x >= 1; x--) {
            var token = str.substring(i, i + x);
            if (token.length < 1) {
                return null;
            }
            if (token.length == 1)return token;
            if (_isInteger_chi(token))return token;
        }
        return null;
    };

    var str2date = function (s, fmt) {
        //赋值
        var s = String.from(s),
            fmt = String.from(fmt),
            i_val = 0,
            i_format = 0,
            c, token, token2, x, y,
            now = new Date(),
            year = now.getFullYear(),
            month = now.getMonth() + 1,
            date = 1,
            hh = now.getHours(),
            mm = now.getMinutes(),
            ss = now.getSeconds(),
            ampm, i;
        while (i_format < fmt.length) {
            c = fmt.charAt(i_format);
            token = '';
            while ((fmt.charAt(i_format) == c) && (i_format < fmt.length)) {
                token += fmt.charAt(i_format++);
            }
            if (['NNNN', 'NN', 'N'].contains(token)) {
                x = (token == 'NNNN') ? 4 : 2;
                y = (token == 'NN') ? 2 : 4;
                //从val字符串中根据val的指针i_val,定义的最小/大长度(如上面的y,它所允许的最大长度就是4,最小长度就是2,例如2009,09等)
                year = _getInt2(s, i_val, x, y);
                if (year == null)return 0;
                year = C2N(year);
                //修改val的指针i_val,使其指向当前的变量
                i_val += year.length;
                if (year.length == 2) {//年输入两位数的作用
                    year = (year > 70) ? (1900 + year) : (2000 + year);
                }
            } else if (token == "Y") {
                month = _getInt_month(s, i_val);
                i_val += month.length;
                month = _C2N(month);
                if (month == null || (month < 1) || (month > 12))return 0;
            } else if (token == "R") {
                date = _getInt_date(s, i_val);
                i_val += date.length;
                date = _C2N(date);
                if (date == null || (date < 1) || (date > 31))return 0;
            } else if (token == "S") { //小时 数字 中文 h
                hh = _getInt_date(s, i_val);
                i_val += hh.length;
                hh = _C2N(hh);
                if (hh == null || (hh < 1) || (hh > 12)) {
                    return 0;
                }
            } else if (token == "T") { //小时 数字 中文  H
                hh = _getInt_date(s, i_val);
                i_val += hh.length;
                hh = _C2N(hh);
                if (hh == null || (hh < 0) || (hh > 23)) {
                    return 0;
                }
            } else if (token == "U") {   //小时 数字 中文 K
                hh = _getInt_date(s, i_val);
                i_val += hh.length;
                hh = _C2N(hh);
                if (hh == null || (hh < 0) || (hh > 11)) {
                    return 0;
                }
            } else if (token == "V") {   //小时 数字 中文 k
                hh = _getInt_date(s, i_val);
                i_val += hh.length;
                hh = _C2N(hh);
                hh--;
                if (hh == null || (hh < 1) || (hh > 24)) {
                    return 0;
                }
            } else if (token == "F") {   //分 数字 中文
                mm = _getInt_date(s, i_val);
                i_val += mm.length;
                mm = _C2N(mm);
                if (mm == null || (mm < 0) || (mm > 59)) {
                    return 0;
                }
            } else if (token == "W") {   //秒 数字 中文
                ss = _getInt_date(s, i_val);
                i_val += ss.length;
                ss = _C2N(ss);
                if (ss == null || (ss < 0) || (ss > 59)) {
                    return 0;
                }
            } else if (['yyyy', 'yy', 'y'].contains(token)) {//年
                x = (token == 'yyyy') ? 4 : 2;
                y = (token == 'yy') ? 2 : 4;
                //从val字符串中根据val的指针i_val,定义的最小/大长度(如上面的y,它所允许的最大长度就是4,最小长度就是2,例如2009,09等)
                year = _getInt(s, i_val, x, y);
                if (year == null) {
                    return 0;
                }
                //修改val的指针i_val,使其指向当前的变量
                i_val += year.length;
                //年输入两位数的作用
                if (year.length == 2) {
                    year += (year > 70) ? 1900 : 2000;
                }
            } else if (token == "MMM" || token == "NNN") {//月_name
                month = 0;
                for (i = 0; i < MONTH_NAMES.length; i++) {
                    var month_name = MONTH_NAMES[i];
                    //如果指针指向的长度与this.MONTH_NAMES中的任何一项都相同
                    if (s.substring(i_val, i_val + month_name.length).toLowerCase() == month_name.toLowerCase()) {
                        if (token == "MMM" || (token == "NNN" && i > 11)) {
                            month = i + 1;
                            if (month > 12) {
                                month -= 12;
                            }
                            i_val += month_name.length;
                            break;
                        }
                    }
                }
                if ((month < 1) || (month > 12)) {
                    return 0;
                }
            } else if (token == "EE" || token == "E") {//日
                for (i = 0; i < DAY_NAMES.length; i++) {
                    var day_name = DAY_NAMES[i];
                    if (s.substring(i_val, i_val + day_name.length).toLowerCase() == day_name.toLowerCase()) {
                        i_val += day_name.length;
                        break;
                    }
                }
            } else if (token == "MM" || token == "M") {//月_数字
                month = _getInt(s, i_val, token.length, 2);
                if (month == null || (month < 1) || (month > 12)) {
                    return 0;
                }
                i_val += month.length;
            } else if (token == "dd" || token == "d") {
                date = _getInt(s, i_val, token.length, 2);
                if (date == null || (date < 1) || (date > 31)) {
                    return 0;
                }
                i_val += date.length;
            } else if (token == "hh" || token == "h") {
                hh = _getInt(s, i_val, token.length, 2);
                if (hh == null || (hh < 1) || (hh > 12)) {
                    return 0;
                }
                i_val += hh.length;
            } else if (token == "HH" || token == "H") {
                hh = _getInt(s, i_val, token.length, 2);
                if (hh == null || (hh < 0) || (hh > 23)) {
                    return 0;
                }
                i_val += hh.length;
            } else if (token == "KK" || token == "K") {
                hh = _getInt(s, i_val, token.length, 2);
                if (hh == null || (hh < 0) || (hh > 11)) {
                    return 0;
                }
                i_val += hh.length;
            } else if (token == "kk" || token == "k") {
                hh = _getInt(s, i_val, token.length, 2);
                if (hh == null || (hh < 1) || (hh > 24)) {
                    return 0;
                }
                i_val += hh.length;
                hh--;
            } else if (token == "mm" || token == "m") {
                mm = _getInt(s, i_val, token.length, 2);
                if (mm == null || (mm < 0) || (mm > 59)) {
                    return 0;
                }
                i_val += mm.length;
            } else if (token == "ss" || token == "s") {
                ss = _getInt(s, i_val, token.length, 2);
                if (ss == null || (ss < 0) || (ss > 59)) {
                    return 0;
                }
                i_val += ss.length;
            } else if (token == "a") {//上午下午
                if (s.substring(i_val, i_val + 2).toLowerCase() == "am") {
                    ampm = "AM";
                }
                else if (val.substring(i_val, i_val + 2).toLowerCase() == "pm") {
                    ampm = "PM";
                }
                else {
                    return 0;
                }
                i_val += 2;
            } else {//最后,没有提供关键字的,将指针继续往下移
                if (s.substring(i_val, i_val + token.length) != token) {
                    return 0;
                }
                else {
                    i_val += token.length;
                }
            }
        }
        //如果有其他的尾随字符导致字符串解析不下去了,那么返回0
        if (i_val != s.length) {
            return 0;
        }
        //对于特殊月份:2月,偶数月的天数进行校验, 测试是否是闰年
        if (month == 2) {
            if (( (year % 4 == 0) && (year % 100 != 0) ) || (year % 400 == 0)) {
                if (date > 29) {
                    return 0;
                }
            } else {
                if (date > 28) {
                    return 0;
                }
            }
        }
        if ((month == 4) || (month == 6) || (month == 9) || (month == 11)) {
            if (date > 30) {
                return 0;
            }
        }
        //对于上午下午的具体显示小时数,进行加减
        if (hh < 12 && ampm == "PM") {
            hh = hh - 0 + 12;
        } else if (hh > 11 && ampm == "AM") {
            hh -= 12;
        }
        //将给定的字符串解析成Data
        return new Date(year, month - 1, date, hh, mm, ss);
    };
    var str2str = function (s, fmt1, fmt2) {
        var tempDate = str2date(s, fmt1);
        if (tempDate == 0) {
            return s;
        }
        var returnVal = date2str(tempDate, fmt2);
        if (returnVal == 0) {
            return s;
        }
        return returnVal;
    };
    this.YCL.datefmt = {
        /**
         * 将时间字符串从fmt1格式转换到fmt2格式
         * @param str 时间字符串
         * @param fmt1 原格式(与str匹配)
         * @param fmt2 目标格式
         */
        str2str:str2str,
        /**
         * 将时间字符串转换为fmt格式
         * @param str
         * @param fmt
         */
        str2Date:str2date,
        /**
         * 将日期对象转换为fmt格式的字符串
         * @param date 日期对象
         * @param fmt  格式
         */
        date2Str:date2str,
        /**
         * 比较两个日期字符串的大小
         * @param d1 日期1
         * @param f1 日期1的格式
         * @param d2 日期2
         * @param f2 日期2的格式
         * @return {true|false}如果d1比d2大,返回true,否则返回false
         */
        compare:compare
    };
})();
